/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License,Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.victor.lib.core;

import com.victor.lib.core.compat.Animatable;
import ohos.agp.components.Component;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.ColorFilter;
import ohos.agp.utils.Rect;
import ohos.media.image.PixelMap;

public class LoadingDrawable extends PixelMapElement implements Animatable, Component.DrawTask {
    private final LoadingRenderer mLoadingRender;
    private Component mComponent;

    private int mIntrinsicHeight;
    private int mIntrinsicWidth;

    private final LoadingRenderer.Callback mCallback = new LoadingRenderer.Callback() {
        public void invalidate() {
            if (mComponent != null) {
                mComponent.invalidate();
            }
        }
    };

    public LoadingDrawable(Component component, LoadingRenderer loadingRender) {
        super((PixelMap) null);
        this.mComponent = component;
        this.mLoadingRender = loadingRender;
        this.mLoadingRender.setCallback(mCallback);
    }

    public void setBounds(Rect bounds) {
        this.mLoadingRender.setBounds(bounds);
    }

    @Override
    public void drawToCanvas(Canvas canvas) {
        if (!getBounds().isEmpty()) {
            this.mLoadingRender.draw(canvas);
        }
    }

    @Override
    public void setAlpha(int alpha) {
        this.mLoadingRender.setAlpha(alpha);
    }


    public void setColorFilter(ColorFilter cf) {
        this.mLoadingRender.setColorFilter(cf);
    }

    @Override
    public void start() {
        this.mLoadingRender.start();
    }

    @Override
    public void stop() {
        this.mLoadingRender.stop();
    }

    @Override
    public boolean isRunning() {
        return this.mLoadingRender.isRunning();
    }

    public int getIntrinsicHeight() {
        return (int) this.mLoadingRender.mHeight;
    }

    public int getIntrinsicWidth() {
        return (int) this.mLoadingRender.mWidth;
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (mIntrinsicWidth != getIntrinsicWidth() || mIntrinsicHeight != getIntrinsicHeight()) {
            mIntrinsicWidth = getIntrinsicWidth();
            mIntrinsicHeight = getIntrinsicHeight();
            this.mLoadingRender.setBounds(new Rect(0, 0, mIntrinsicWidth, mIntrinsicHeight));
        }
        if (!mLoadingRender.mBounds.isEmpty()) {
            // We use DrawTask to implement Drawable's function for now (Maybe we'll change it to Element in future).
            // Since DrawTask doesn't have its own bounds, we need to do some transformation to make it FIT_CENTER.
            int saveState = canvas.save();
            float vWidth = component.getWidth();
            float vHeight = component.getHeight();
            float dWidth = mLoadingRender.mWidth;
            float dHeight = mLoadingRender.mHeight;
            float scale = Math.min(vWidth / dWidth, vHeight / dHeight);
            canvas.scale(scale, scale, vWidth / 2f, vHeight / 2f);
            canvas.translate((vWidth - dWidth) / 2f, (vHeight - dHeight) / 2f);
            this.mLoadingRender.draw(canvas);
            canvas.restoreToCount(saveState);
        }
    }
}
